from rest_framework import serializers
from django.contrib.auth.models import User
from .models import Category, Product, Review, Tag, ProductTag


# 1. 基础ModelSerializer - 最常用的序列化器
class CategorySerializer(serializers.ModelSerializer):
    """基础的ModelSerializer示例"""
    products_count = serializers.SerializerMethodField()

    class Meta:
        model = Category
        fields = ['id', 'name', 'description', 'created_at', 'updated_at', 'products_count']
        read_only_fields = ['created_at', 'updated_at']

    def get_products_count(self, obj):
        """计算分类下的产品数量"""
        return obj.products.count()


# 2. 手动Serializer - 完全手动控制字段
class CategoryManualSerializer(serializers.Serializer):
    """手动定义字段的Serializer示例，与CategorySerializer对比"""
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField(max_length=100)
    description = serializers.CharField(required=False, allow_blank=True)
    created_at = serializers.DateTimeField(read_only=True)
    updated_at = serializers.DateTimeField(read_only=True)
    products_count = serializers.SerializerMethodField()

    def create(self, validated_data):
        return Category.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.name = validated_data.get('name', instance.name)
        instance.description = validated_data.get('description', instance.description)
        instance.save()
        return instance

    def get_products_count(self, obj):
        return obj.products.count()


# 3. 嵌套序列化器 - 包含关联对象
class UserSerializer(serializers.ModelSerializer):
    """用户序列化器"""
    class Meta:
        model = User
        fields = ['id', 'username', 'email', 'first_name', 'last_name']


class ReviewSerializer(serializers.ModelSerializer):
    """评论序列化器 - 包含嵌套的用户信息"""
    reviewer = UserSerializer(read_only=True)
    reviewer_name = serializers.CharField(source='reviewer.username', read_only=True)

    class Meta:
        model = Review
        fields = ['id', 'rating', 'comment', 'created_at', 'updated_at',
                 'reviewer', 'reviewer_name']
        read_only_fields = ['created_at', 'updated_at']


# 4. 深度嵌套序列化器
class ProductDetailSerializer(serializers.ModelSerializer):
    """产品详情序列化器 - 包含多层嵌套"""
    category = CategorySerializer(read_only=True)
    category_id = serializers.IntegerField(write_only=True)
    reviews = ReviewSerializer(many=True, read_only=True)
    created_by = UserSerializer(read_only=True)
    average_rating = serializers.SerializerMethodField()
    reviews_count = serializers.SerializerMethodField()

    class Meta:
        model = Product
        fields = ['id', 'name', 'description', 'price', 'category', 'category_id',
                 'status', 'stock', 'image', 'created_at', 'updated_at',
                 'created_by', 'reviews', 'average_rating', 'reviews_count']
        read_only_fields = ['created_at', 'updated_at', 'created_by']

    def get_average_rating(self, obj):
        """计算平均评分"""
        reviews = obj.reviews.all()
        if reviews.exists():
            return sum(review.rating for review in reviews) / reviews.count()
        return 0

    def get_reviews_count(self, obj):
        """计算评论数量"""
        return obj.reviews.count()


# 5. 简单列表序列化器
class ProductListSerializer(serializers.ModelSerializer):
    """产品列表序列化器 - 用于列表展示，字段较少"""
    category_name = serializers.CharField(source='category.name', read_only=True)
    created_by_username = serializers.CharField(source='created_by.username', read_only=True)

    class Meta:
        model = Product
        fields = ['id', 'name', 'price', 'category_name', 'status', 'stock',
                 'created_by_username', 'created_at']


# 6. 自定义字段序列化器
class ProductCreateUpdateSerializer(serializers.ModelSerializer):
    """产品创建/更新序列化器 - 包含自定义验证"""
    price = serializers.DecimalField(max_digits=10, decimal_places=2, min_value=0)
    stock = serializers.IntegerField(min_value=0)

    class Meta:
        model = Product
        fields = ['name', 'description', 'price', 'category', 'status', 'stock', 'image']

    def validate_name(self, value):
        """自定义名称验证"""
        if len(value) < 3:
            raise serializers.ValidationError("产品名称至少需要3个字符")
        return value

    def validate(self, data):
        """对象级验证"""
        if data.get('status') == 'active' and data.get('stock', 0) == 0:
            raise serializers.ValidationError("在售商品必须有库存")
        return data


# 7. 多对多关系序列化器
class TagSerializer(serializers.ModelSerializer):
    """标签序列化器"""
    class Meta:
        model = Tag
        fields = ['id', 'name', 'color']


class ProductTagSerializer(serializers.ModelSerializer):
    """产品标签关联序列化器"""
    tag = TagSerializer(read_only=True)
    tag_id = serializers.IntegerField(write_only=True)
    added_by = UserSerializer(read_only=True)

    class Meta:
        model = ProductTag
        fields = ['id', 'tag', 'tag_id', 'added_by', 'added_at']
        read_only_fields = ['added_at', 'added_by']


# 8. 动态字段序列化器
class DynamicFieldsModelSerializer(serializers.ModelSerializer):
    """
    动态字段序列化器基类
    允许通过请求参数控制返回的字段
    用法: ProductSerializer(product, fields=['name', 'price'])
    """
    def __init__(self, *args, **kwargs):
        fields = kwargs.pop('fields', None)
        super().__init__(*args, **kwargs)

        if fields is not None:
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)


class DynamicProductSerializer(DynamicFieldsModelSerializer):
    """支持动态字段的产品序列化器"""
    category = CategorySerializer(read_only=True)
    created_by = UserSerializer(read_only=True)

    class Meta:
        model = Product
        fields = '__all__'


# 9. 只读和只写序列化器对比
class ProductReadOnlySerializer(serializers.ModelSerializer):
    """只读产品序列化器 - 用于展示完整信息"""
    category = CategorySerializer(read_only=True)
    created_by = UserSerializer(read_only=True)
    reviews = ReviewSerializer(many=True, read_only=True)

    class Meta:
        model = Product
        fields = '__all__'


class ProductWriteOnlySerializer(serializers.ModelSerializer):
    """只写产品序列化器 - 用于创建和更新"""

    class Meta:
        model = Product
        fields = ['name', 'description', 'price', 'category', 'status', 'stock', 'image']
        extra_kwargs = {
            'name': {'write_only': True},
            'description': {'write_only': True},
            'price': {'write_only': True},
            'category': {'write_only': True},
            'status': {'write_only': True},
            'stock': {'write_only': True},
            'image': {'write_only': True},
        }


# 10. HyperlinkedModelSerializer - 使用超链接而不是主键
class HyperlinkedCategorySerializer(serializers.HyperlinkedModelSerializer):
    """使用超链接的分类序列化器"""
    products = serializers.HyperlinkedRelatedField(
        many=True,
        read_only=True,
        view_name='product-detail'
    )

    class Meta:
        model = Category
        fields = ['url', 'id', 'name', 'description', 'products', 'created_at']
        extra_kwargs = {
            'url': {'view_name': 'category-detail'},
        }


# 11. 图片上传序列化器
class ProductImageUploadSerializer(serializers.ModelSerializer):
    """产品图片上传序列化器 - 专门用于处理图片上传"""

    class Meta:
        model = Product
        fields = ['id', 'image']
        read_only_fields = ['id']

    def validate_image(self, value):
        """验证图片文件"""
        if value:
            # 验证文件大小 (5MB 以内)
            if value.size > 5 * 1024 * 1024:
                raise serializers.ValidationError("图片文件大小不能超过 5MB")

            # 验证文件类型
            if not value.content_type.startswith('image/'):
                raise serializers.ValidationError("只支持图片文件")

            # 验证图片格式
            allowed_formats = ['JPEG', 'PNG', 'GIF', 'WebP']
            try:
                from PIL import Image
                image = Image.open(value)
                if image.format not in allowed_formats:
                    raise serializers.ValidationError(
                        f"不支持的图片格式，只支持: {', '.join(allowed_formats)}"
                    )

                # 验证图片尺寸
                if image.width > 2000 or image.height > 2000:
                    raise serializers.ValidationError("图片尺寸不能超过 2000x2000 像素")

            except Exception as e:
                raise serializers.ValidationError(f"图片文件损坏或无效: {str(e)}")

        return value


class ProductImageSerializer(serializers.ModelSerializer):
    """产品图片信息序列化器 - 用于返回图片信息"""
    image_url = serializers.SerializerMethodField()
    image_size = serializers.SerializerMethodField()

    class Meta:
        model = Product
        fields = ['id', 'name', 'image', 'image_url', 'image_size']

    def get_image_url(self, obj):
        """获取图片完整URL"""
        if obj.image:
            request = self.context.get('request')
            if request:
                return request.build_absolute_uri(obj.image.url)
            return obj.image.url
        return None

    def get_image_size(self, obj):
        """获取图片尺寸信息"""
        if obj.image:
            try:
                from PIL import Image
                with Image.open(obj.image.path) as img:
                    return {
                        'width': img.width,
                        'height': img.height,
                        'format': img.format,
                        'size': obj.image.size  # 文件大小
                    }
            except Exception:
                return None
        return None
